//
// Created by gogoqiu on 2021/10/12.
//

#include "ListViewAdapter.h"
#include "../data/PreferenceStorage.h"
#include "../src/MyObj.h"
#include "../../librapidsvn/include/ids.hpp"
//#include "../librapidsvn/include/action_event.hpp"

/*
void ExecuteAction()
{
    if ( action == nullptr )
        return;
    //?
    ActionEvent event ( parent, TOKEN_ACTION_START );

    {
        //???
        event.init ( parent, TOKEN_ACTION_START,
                     LogItem_Normal, _ ( "Execute:" ), actionName );
        event.Post();
    }

    unsigned int actionFlags = 0;

    try {
        state = ACTION_RUNNING;
        //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        if ( !action->Perform() )
            result = ACTION_ERROR;
        else
            result = ACTION_SUCCESS;
        //
        actionFlags = action->GetFlags();

        state = ACTION_NONE;
    } catch ( svn::ClientException & e ) {
        wxString msg, errTxt ( Utf8ToLocal ( e.message() ) );
        msg.Printf ( _ ( "Error while performing action: %s" ),
                     errTxt.c_str() );

        event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
        event.Post();

        state = ACTION_NONE;
        result = ACTION_ERROR;
        DeleteAction();
        return;
    } catch ( ... ) {
        wxString msg ( _ ( "Error while performing action." ) );

        event.init ( parent, TOKEN_SVN_INTERNAL_ERROR, msg );
        event.Post();

        state = ACTION_NONE;
        result = ACTION_ERROR;
        DeleteAction();
        return;
    }
    //actionFlags
    event.init ( parent, TOKEN_ACTION_END,
                 ( void* ) new unsigned int ( actionFlags ) );
    event.Post();
    DeleteAction();
}
*/

/**
 * auto * entries = const_cast<svn::LogEntries *>(client.log(target.c_str(), m->data.startRevision,
                              svn::Revision::START, LogAction::LogLimit + 1, true, false));
  std::reverse(entries->begin(), entries->end());

  auto * data = new LogNextData(m->data.path, m->data.startRevision,
                                       svn::Revision::HEAD, m->data.logdlg,
                                       (svn::LogEntries *) entries);
  //对接到frame::OnActionEvent
  ActionEvent::Post(GetParent(), TOKEN_LOG_NEXT_CALLBACK, data);


  void MainFrame::OnActionEvent ( wxCommandEvent & event )
  如何处理的
  在frame处理模块里重载OnActionEvent ( wxCommandEvent & event )函数
  耗时异步项目
  thread

 */
//template< class DataType, class BaseViewHolder >
//int ListViewAdapter<DataType, BaseViewHolder>::ID_DATA_SET_CHANGED = 555;

template<class DataType, class BaseViewHolder>
ListViewAdapter<DataType, BaseViewHolder>::ListViewAdapter( wxWindow *parent, wxScrolledWindow* listbox )
        :parent( parent ), m_listbox(listbox){

};

template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::clearItemsWithNotify(){
    items.clear();
    notifyDataSetChanged();
}

//action side, client side, thread side
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::setItemsWithNotify (  vector<DataType*> infos )
{
    this->items.clear();
    for( DataType* item: infos ){
        this->items.push_back( item );
    }
    //this->items.addAll ( infos );
    notifyDataSetChanged();
}

/**
 * frame:
 *  //dialogRootBoxSizer->Add(m_listbox
 *  wxScrolledWindow* m_listbox
 *  wxBoxSizer *dialogRootBoxSizer
 *
 * onCreateViewHolder:
 *  wxBoxSizer* panelRootBoxSizer
 *
 * android:
 *
 */
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::OnFrameGetItems( int startPosition, vector<DataType*> _items ){
    //接收到的数据
    //
    BaseViewHolder* baseViewHolder;
    int i = 0;
    wxWindowList list = m_listbox->GetChildren();
    //wxWindowListNode *w = list.GetFirst();
    wxWindowListNode* w;
    for( i=startPosition; i<list.size(); i++ ){
        m_listbox->RemoveChild( list.operator[](i) );
        //list.[i];
    }
    //m_listbox->RemoveChild()
    for( DataType* item : _items ){
        //
        baseViewHolder = onCreateViewHolder( 0 );
        //put the values into view
        //onBindViewHolder( baseViewHolder, item );
        //
        m_listbox->AddChild( baseViewHolder );
    }
}

/*
 * main:
 * dialogRootBoxSizer = new wxBoxSizer(wxVERTICAL);
    m_listbox = new wxScrolledWindow(this, wxID_ANY,
                                     wxDefaultPosition, wxDefaultSize, wxHSCROLL | wxVSCROLL );
    m_listbox->SetScrollRate(5, 5 );
    //
    dialogRootBoxSizer->Add(m_listbox, 1, wxEXPAND, 0 );
    panelRootBoxSizer = new wxBoxSizer(wxVERTICAL);

   iterator
    m_panel = new ListItemPanel( this, _iterator.operator*() );
        //
    panelRootBoxSizer->Add(m_panel, 0,
                       wxEXPAND|wxALL, 15);
 */

template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::notifyDataSetChanged() {
    /*
     * auto *object = new MyObj( data );
    //
    Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler( PreferenceViewHolder<PreferenceData>::OnClickItem ),
            object, this );
    ActionEvent event ( parent, event_id, data );
    event.Post();
     */
    //ActionEvent::Post( parent, ID_DATA_SET_CHANGED, items );
    //pack and post
    auto *event = new wxCommandEvent ( wxEVT_COMMAND_MENU_SELECTED, ACTION_EVENT );
    event->SetInt (ID_DATA_SET_CHANGED );
    event->SetClientData( &items );
    wxPostEvent ( this->parent, *event );
}

/**
 * @param holder The ViewHolder which should be updated to represent the contents of the
 *               item at the given position in the data set.
 * @param position The position of the item within the adapter's data set.
 */
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::onBindViewHolder(BaseViewHolder *holder,
                                                 int position) {
    onBindViewHolder( holder, items.at(position));
}

/*
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::onBindViewHolder(BaseViewHolder *holder,
                                                 DataType date ) {

}
*/

/**
 * @param parent The ViewGroup into which the new View will be added after it is bound to
 *               an adapter position.
 * @param viewType The view type of the new View.
 */
template<class DataType, class BaseViewHolder>
BaseViewHolder *ListViewAdapter<DataType, BaseViewHolder>::onCreateViewHolder( int viewType,  DataType * data ) {
    return nullptr;
}

template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::onBindViewHolder(BaseViewHolder *holder, DataType *date) {

}

template<class DataType, class BaseViewHolder>
struct ListViewAdapter<DataType, BaseViewHolder>::Item_range_inserted_package{
    int startPosition;
    int itemCount;
    vector<DataType*> items;
    Item_range_inserted_package(){
        startPosition =0;
        itemCount = 0;
    }
};

template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::appendItemsWithNotify (  vector<DataType*> infos )
{
    int startPosition = this->items.size();
    //this->items.addAll ( infos );
    for( DataType* item: infos ){
        this->items.push_back( item );
    }
    notifyItemRangeInserted ( startPosition, infos.size() );
}

/**
 * 涵盖在这里面
 * void MainFrame::OnActionEvent ( wxCommandEvent & event )
 *
 * MainFrame::request
 * use a thread
 * adapter->appendItems
 * notifyDataSetChanged
 * 消息的种类
 * https://blog.csdn.net/weixin_30724853/article/details/99792611?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-7.no_search_link
 *
 */
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::OnActionEvent(wxCommandEvent &event) {
    const int token = event.GetInt();
    const long liType = event.GetExtraLong();
    void *p;
    vector<DataType*> *items;
    Item_range_inserted_package *insertedPackage;
    //vector<PreferenceView *> v;
    switch ( token ) {
        case ListViewAdapter::ID_DATA_SET_CHANGED:
            p = event.GetClientData();
            if ( p != nullptr ) {
                //auto *myObj = reinterpret_cast<MyObj *>(event.GetEventUserData());
                //auto *items = reinterpret_cast<vector<DataType*>>(myObj->data);
                items = reinterpret_cast<vector<DataType*>>( event.GetEventUserData() );
                // copy the data first. This makes sure
                // the memory is released in the occurrence
                // of an exception
                OnFrameGetItems( 0, *items );
            }
            break;
        case ID_ITEM_RANGE_INSERTED:
            p = event.GetClientData();
            if ( p != nullptr ) {
                insertedPackage = reinterpret_cast<Item_range_inserted_package*>( event.GetEventUserData() );
                OnFrameGetItems( insertedPackage->startPosition, insertedPackage->items );
            }
            break;
    }
}

/*
 *
 */
/*
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::notifyItemRangeInserted( int startPosition, vector<DataType> items ) {
    auto *event = new wxCommandEvent ( wxEVT_COMMAND_MENU_SELECTED, ACTION_EVENT );
    event->SetInt ( ID_ITEM_RANGE_INSERTED );
    Item_range_inserted_package insertedPackage;
    insertedPackage.startPosition = startPosition;
    insertedPackage.items = items;
    event->SetClientData( insertedPackage );
    wxPostEvent ( this->parent, *this->event );
}
*/
template<class DataType, class BaseViewHolder>
void ListViewAdapter<DataType, BaseViewHolder>::notifyItemRangeInserted( int startPosition, int itemCount ) {
    auto *event = new wxCommandEvent ( wxEVT_COMMAND_MENU_SELECTED, ACTION_EVENT );
    event->SetInt ( ID_ITEM_RANGE_INSERTED );
    Item_range_inserted_package insertedPackage;
    insertedPackage.startPosition = startPosition;
    insertedPackage.itemCount = itemCount;
    insertedPackage.items = items;
    event->SetClientData( &insertedPackage );
    wxPostEvent ( this->parent, *event );
}

static void test(){
    new ListViewAdapter<wxString, PreferenceItem>(nullptr , nullptr );
}
